// MqttClient.js - MQTT客户端通信管理

/**
 * MQTT客户端通信类
 */
class MqttClient {
    constructor() {
        this.client = null;       // MQTT客户端
        this.broker = '';         // 服务器地址
        this.port = '';           // 端口
        this.clientId = '';       // 客户端ID
        this.username = '';       // 用户名
        this.password = '';       // 密码
        this.isConnected = false;  // 连接状态
        this.subscriptions = [];   // 订阅的主题列表
        this.heartbeatTimer = null; // 心跳计时器
        this.lastHeartbeatTime = 0; // 最后一次心跳时间
        this.connectionStatusCallback = null; // 连接状态回调
        this.messageCallback = null; // 消息接收回调

        // 定义主题前缀
        this.baseTopic = 'device';
        this.commandTopic = `${this.baseTopic}/command`;         // 发送命令的主题
        this.responseTopic = `${this.baseTopic}/response`;       // 接收响应的主题
        this.heartbeatTopic = `${this.baseTopic}/heartbeat`;     // 心跳主题
    }

    /**
     * 初始化MQTT连接
     * @param {Object} config - MQTT配置
     * @param {string} config.broker - 服务器地址
     * @param {string|number} config.port - 服务器端口
     * @param {string} config.clientId - 客户端ID
     * @param {string} config.username - 用户名
     * @param {string} config.password - 密码
     * @param {Function} statusCallback - 状态回调函数
     * @param {Function} messageCallback - 消息回调函数
     */
    connect(config, statusCallback, messageCallback) {
        this.broker = config.broker || 'localhost';
        this.port = config.port || 1883;
        this.clientId = config.clientId || `mqtt_client_${Math.random().toString(16).slice(2, 10)}`;
        this.username = config.username || '';
        this.password = config.password || '';
        this.connectionStatusCallback = statusCallback;
        this.messageCallback = messageCallback;

        // 自定义主题前缀（如果有）
        if (config.baseTopic) {
            this.baseTopic = config.baseTopic;
            this.commandTopic = `${this.baseTopic}/command`;
            this.responseTopic = `${this.baseTopic}/response`;
            this.heartbeatTopic = `${this.baseTopic}/heartbeat`;
        }

        // 关闭现有连接
        this.disconnect();

        try {
            // 使用uni-app的MQTT插件
            const connectionOptions = {
                host: this.broker,
                port: this.port,
                clientId: this.clientId,
                username: this.username,
                password: this.password,
                keepalive: 60, // 保活时间
                clean: true,  // 清除会话
                connectTimeout: 30 * 1000, // 连接超时
                reconnect: true // 自动重连
            };

            // 创建MQTT客户端
            this.client = uni.requireNativePlugin('MQTT');

            // 设置连接回调
            this.client.setOnConnectListener(() => {
                console.log('MQTT连接已建立');
                this.isConnected = true;
                this.lastHeartbeatTime = Date.now();
                this.startHeartbeatMonitor();
                this._subscribeToTopics();

                if (this.connectionStatusCallback) {
                    this.connectionStatusCallback(true);
                }
            });

            // 设置断开连接回调
            this.client.setOnDisconnectListener(() => {
                console.log('MQTT连接已断开');
                this.isConnected = false;
                this.clearHeartbeatMonitor();

                if (this.connectionStatusCallback) {
                    this.connectionStatusCallback(false);
                }
            });

            // 设置连接失败回调
            this.client.setOnFailureListener((error) => {
                console.error('MQTT连接失败', error);
                this.isConnected = false;
                this.clearHeartbeatMonitor();

                if (this.connectionStatusCallback) {
                    this.connectionStatusCallback(false, error);
                }
            });

            // 设置消息接收回调
            this.client.setOnMessageArriveListener((topic, message) => {
                this.handleMessage(topic, message);
            });

            // 开始连接
            this.client.connect(connectionOptions);

            console.log('MQTT连接请求已发送');
            return true;
        } catch (error) {
            console.error('MQTT连接请求发送失败', error);
            if (this.connectionStatusCallback) {
                this.connectionStatusCallback(false, error);
            }
            return false;
        }
    }

    /**
     * 订阅主题
     * @private
     */
    _subscribeToTopics() {
        if (!this.isConnected || !this.client) return;

        // 订阅响应主题
        this.client.subscribe(this.responseTopic, 0, (status) => {
            if (status) {
                console.log(`已订阅主题: ${this.responseTopic}`);
                this.subscriptions.push(this.responseTopic);
            } else {
                console.error(`订阅主题失败: ${this.responseTopic}`);
            }
        });

        // 订阅心跳主题
        this.client.subscribe(this.heartbeatTopic, 0, (status) => {
            if (status) {
                console.log(`已订阅主题: ${this.heartbeatTopic}`);
                this.subscriptions.push(this.heartbeatTopic);
            } else {
                console.error(`订阅主题失败: ${this.heartbeatTopic}`);
            }
        });
    }

    /**
     * 断开连接
     */
    disconnect() {
        this.clearHeartbeatMonitor();
        if (this.client && this.isConnected) {
            // 取消所有订阅
            this.subscriptions.forEach(topic => {
                this.client.unsubscribe(topic);
            });

            // 断开连接
            this.client.disconnect();
            this.isConnected = false;
            this.subscriptions = [];
            console.log('MQTT连接已主动关闭');
        }
        this.client = null;
    }

    /**
     * 启动心跳监控
     */
    startHeartbeatMonitor() {
        this.clearHeartbeatMonitor();
        this.heartbeatTimer = setInterval(() => {
            const currentTime = Date.now();

            // 发送心跳
            this.sendHeartbeat();

            // 如果超过30秒没有收到心跳，认为连接已断开
            if (currentTime - this.lastHeartbeatTime > 30000) {
                console.log('心跳超时，断开连接');
                this.disconnect();
                if (this.connectionStatusCallback) {
                    this.connectionStatusCallback(false, { message: '心跳超时' });
                }
            }
        }, 15000); // 每15秒发送一次心跳
    }

    /**
     * 发送心跳
     */
    sendHeartbeat() {
        if (!this.isConnected || !this.client) return;

        // 心跳数据固定为: A5 00 12 59 4A A1 B2 C3 D4 E5 F6 A7 B8 C9 D0 F1 F2 EA
        const heartbeatData = 'A5 00 12 59 4A A1 B2 C3 D4 E5 F6 A7 B8 C9 D0 F1 F2 EA';
        this.publishMessage(this.heartbeatTopic, heartbeatData);
    }

    /**
     * 清除心跳监控
     */
    clearHeartbeatMonitor() {
        if (this.heartbeatTimer) {
            clearInterval(this.heartbeatTimer);
            this.heartbeatTimer = null;
        }
    }

    /**
     * 处理接收到的消息
     * @param {string} topic - 消息主题
     * @param {string} message - 消息内容
     */
    handleMessage(topic, message) {
        if (!topic || !message) return;

        try {
            console.log(`接收到消息，主题: ${topic}, 内容: ${message}`);

            // 是否是心跳消息
            if (topic === this.heartbeatTopic) {
                this.lastHeartbeatTime = Date.now();
                console.log('接收到心跳数据');

                // 回调心跳消息
                if (this.messageCallback) {
                    // 将十六进制字符串转换为数组
                    const dataArray = this.hexStringToArray(message);

                    this.messageCallback({
                        isHeartbeat: true,
                        topic: topic,
                        data: dataArray
                    });
                }
                return;
            }

            // 处理设备响应消息
            if (topic === this.responseTopic) {
                // 尝试导入命令解析器
                let MqttCommandSender;
                try {
                    MqttCommandSender = require('./MqttCommandSender.js').default;

                    // 将消息内容转换为Uint8Array
                    const dataArray = this.hexStringToArray(message);
                    const dataView = new Uint8Array(dataArray);

                    // 使用命令解析器解析响应
                    const response = MqttCommandSender.parseResponse(dataView);

                    if (response) {
                        console.log('解析设备响应成功:', response);

                        if (this.messageCallback) {
                            this.messageCallback(response);
                        }
                    } else {
                        console.error('无法解析设备响应');
                        // 返回原始数据，让上层应用决定如何处理
                        if (this.messageCallback) {
                            this.messageCallback({
                                format: 'UNKNOWN',
                                topic: topic,
                                rawData: dataArray
                            });
                        }
                    }
                } catch(e) {
                    console.error('导入命令解析器失败', e);

                    // 回调原始消息
                    if (this.messageCallback) {
                        this.messageCallback({
                            format: 'RAW',
                            topic: topic,
                            message: message
                        });
                    }
                }
                return;
            }

            // 其他主题的消息
            if (this.messageCallback) {
                this.messageCallback({
                    format: 'UNKNOWN',
                    topic: topic,
                    message: message
                });
            }
        } catch (error) {
            console.error('处理消息异常:', error);
        }
    }

    /**
     * 发布消息
     * @param {string} topic - 主题
     * @param {string} message - 消息内容
     * @param {number} qos - 服务质量 (0, 1, 2)
     * @param {boolean} retained - 是否保留消息
     * @returns {boolean} - 是否发送成功
     */
    publishMessage(topic, message, qos = 0, retained = false) {
        if (!this.isConnected || !this.client) {
            console.error('MQTT未连接，无法发送数据');
            return false;
        }

        try {
            this.client.publish({
                topic: topic,
                payload: message,
                qos: qos,
                retained: retained
            }, (success) => {
                if (success) {
                    console.log(`消息发布成功: ${topic}, ${message}`);
                } else {
                    console.error(`消息发布失败: ${topic}`);
                }
            });
            return true;
        } catch (error) {
            console.error('发布消息异常:', error);
            return false;
        }
    }

    /**
     * 发送命令
     * @param {string} commandHex - 十六进制命令字符串
     * @returns {boolean} - 是否发送成功
     */
    sendHexData(commandHex) {
        return this.publishMessage(this.commandTopic, commandHex);
    }

    /**
     * 将十六进制字符串转换为字节数组
     * @param {string} hexString - 十六进制字符串，如"A5 00 12"
     * @returns {Array} - 转换后的字节数组
     */
    hexStringToArray(hexString) {
        // 移除所有空格
        hexString = hexString.replace(/\s+/g, '');

        if (hexString.length % 2 !== 0) {
            throw new Error('十六进制字符串长度必须是偶数');
        }

        const result = [];
        for (let i = 0; i < hexString.length; i += 2) {
            result.push(parseInt(hexString.substr(i, 2), 16));
        }

        return result;
    }

    /**
     * 将字节数组转换为十六进制字符串
     * @param {Array|Uint8Array} array - 字节数组
     * @returns {string} - 转换后的十六进制字符串，如"A5 00 12"
     */
    arrayToHexString(array) {
        return Array.from(array)
            .map(byte => byte.toString(16).padStart(2, '0').toUpperCase())
            .join(' ');
    }
}

// 导出MQTT客户端实例
export default new MqttClient();